package com.min.netty.file.handler;

import com.min.netty.file.constant.Constant;
import com.min.netty.file.constant.TransferFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.apache.commons.io.FileUtils;

import java.io.IOException;
import java.io.RandomAccessFile;

public class MinFileClientHandler extends ChannelInboundHandlerAdapter {
    private static final Logger LOGGER = LoggerFactory.getLogger(MinFileClientHandler.class);
    private final TransferFile file;
    private RandomAccessFile randomAccessFile = null;
    private long fileSize = 0L;
    private long startTime = 0L;

    public MinFileClientHandler(TransferFile file) {
        this.file = file;
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        if (randomAccessFile != null) {
            randomAccessFile.close();
        }
        if (LOGGER.isDebugEnabled()) {
            float time = (System.currentTimeMillis() - this.startTime) / 1000.0F;
            LOGGER.debug("====传输完毕，共计{}，耗时={} s，速度={} kb/s",
                    FileUtils.byteCountToDisplaySize(fileSize), time, fileSize / time / 1024.0F);
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws IOException {
        // 只读方式打开要上传的文件，在通道Inactive时，关闭文件
        this.randomAccessFile = new RandomAccessFile(file.getFile(), Constant.FILE_READ);
        this.fileSize = randomAccessFile.length();
        if (LOGGER.isDebugEnabled()) {
            this.startTime = System.currentTimeMillis();
            LOGGER.debug("====数据通道建立，{}", ctx.channel().remoteAddress());
        }
        // 发送文件的md5到服务端，验证是否秒传
        ctx.channel().writeAndFlush(file.getMd5());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        if (msg instanceof Integer) {
            // 接收服务器发送的偏移量
            int start = (Integer) msg;
            if (Constant.TRANSMIT_MD5_EXISTS == start) {
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("====文件秒传完毕，{}", file.getFile().toURI());
                }
                ctx.close();
            } else if (start >= Constant.TRANSMIT_START) {
                // 设置读文件的起始点
                file.setStarPos(start);
                randomAccessFile.seek(start);
                // 剩余未读的字节长度
                long remaining = fileSize - start;
                remaining = remaining > 0 ? remaining : 0;
                byte[] bytes;
                if (remaining > Constant.SEND_SIZE) {
                    bytes = new byte[Constant.SEND_SIZE];
                } else {
                    // 剩余部分不足单次发送数据长度，则将剩余部分全部发送，也就意味着这是最后一部分数据。
                    bytes = new byte[(int) remaining];
                }
                int byteRead;
                if (remaining > 0 && (byteRead = randomAccessFile.read(bytes)) != -1) {
                    file.setEndPos(byteRead);
                    file.setBytes(bytes);
                    ctx.writeAndFlush(file);
                } else {
                    randomAccessFile.close();
                    ctx.close();
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("====文件传输完毕，{}", file.getFile().toURI());
                    }
                }
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
        cause.printStackTrace();
    }
}
